package com.yuyue.springFramework.note11.entity.custom2;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 事件广播的实现类
 */
@Component("eventMulticaster")
public class SimpleEventMulticaster implements EventMulticaster {
    //事件监听器集合
    private Map<Class<?>, List<EventListener>> eventObjectListenerMap = new ConcurrentHashMap<>();

    //无参构造
    public SimpleEventMulticaster(){}

    /**
     * 以监听器集合作为参数的构造器
     * @param eventListeners
     */
    @Autowired(required = false)
    public SimpleEventMulticaster(List<EventListener> eventListeners){
        if(eventListeners != null){
            //使用lambda表达式调用 EventMulticaster.addEventListener 方法添加监听器
            eventListeners.forEach(this :: addEventListener);
        }
    }

    /**
     * 广播事件给所有的监听器，对事件感兴趣的监听器会处理该事件
     * @param event
     */
    @Override
    public void multicasterEvent(AbstractEvent event) {
        //获取事件对应的监听器集合
        List<EventListener> eventListeners = this.eventObjectListenerMap.get(event.getClass());

        if(eventListeners != null){
            //遍历事件监听器，处理事件
            for (EventListener eventListener : eventListeners) {
                eventListener.onEvent(event);
            }
        }
    }

    /**
     * 获取监听器的事件类型
     * @param eventListener
     * @return
     */
    public Class<?> getEventType(EventListener eventListener){
        //获取参数类型
        ParameterizedType parameterizedType = (ParameterizedType) eventListener.getClass().getGenericInterfaces()[0];
        //获取实际类型
        Type type = parameterizedType.getActualTypeArguments()[0];
        return (Class<?>) type;
    }

    /**
     * 添加一个事件监听器
     * @param eventListener
     */
    @Override
    public void addEventListener(EventListener<?> eventListener) {
        //获取监听器对应的事件类型
        Class<?> eventType = getEventType(eventListener);
        //获取事件对应的监听器列表
        List<EventListener> eventListeners = this.eventObjectListenerMap.get(eventType);
        //列表为空，创建监听器列表
        if(eventListeners == null){
            eventListeners = new ArrayList<>();

            this.eventObjectListenerMap.put(eventType, eventListeners);
        }

        //放入监听器
        eventListeners.add(eventListener);
    }

    /**
     * 移除一个事件监听器
     * @param eventListener
     */
    @Override
    public void removeEventListener(EventListener<?> eventListener) {
        //获取监听器对应的事件类型
        Class<?> eventType = getEventType(eventListener);

        //获取事件对应的监听器列表
        List<EventListener> eventListeners = this.eventObjectListenerMap.get(eventType);

        //移除监听器
        if(eventListeners != null){
            eventListeners.remove(eventListener);
        }
    }
}
